package com.example.demo20230927;

import org.springframework.web.util.UriComponentsBuilder;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.net.URLEncoder;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;
import java.util.Map;
import java.util.SortedMap;
import java.util.TreeMap;
import java.util.UUID;

public class AuthUtil {

    private static final String HMAC_SHA256 = "HmacSHA256";

    public static String genNonce() {
        return UUID.randomUUID().toString().replaceAll("-", "");
    }

    public static String genCanonicalQueryString(Map<String, String> params) {
        if (params == null || params.isEmpty()) {
            return "";
        }

        SortedMap<String, String> sortedParams = new TreeMap<>(params);
        UriComponentsBuilder builder = UriComponentsBuilder.newInstance();

        sortedParams.forEach((key, value) -> builder.queryParam(urlEncode(key), urlEncode(value)));

        String query = builder.build().encode().toUriString();
        return query.substring(1); // Remove the leading "?" character
    }

    public static String genSignature(String appKey, String signingString) {
        try {
            Mac sha256_HMAC = Mac.getInstance(HMAC_SHA256);
            SecretKeySpec secret_key = new SecretKeySpec(appKey.getBytes(), HMAC_SHA256);
            sha256_HMAC.init(secret_key);

            return Base64.getEncoder().encodeToString(sha256_HMAC.doFinal(signingString.getBytes()));
        } catch (NoSuchAlgorithmException | InvalidKeyException e) {
            // Log and handle the exception
            throw new RuntimeException("Error generating signature", e);
        }
    }

    public static Map<String, String> genSignHeaders(String appId, String appKey, String method, String uri, Map<String, String> query) {
        String nonce = genNonce();
        String timestamp = String.valueOf(System.currentTimeMillis() / 1000);
        String canonicalQuery = genCanonicalQueryString(query);

        String signingString = method.toUpperCase() + "\n"
                + uri + "\n"
                + canonicalQuery + "\n"
                + appId + "\n"
                + timestamp + "\n"
                + nonce;

        String signature = genSignature(appKey, signingString);

        // Construct the headers
        Map<String, String> headers = new TreeMap<>();
        headers.put("X-AI-GATEWAY-APP-ID", appId);
        headers.put("X-AI-GATEWAY-TIMESTAMP", timestamp);
        headers.put("X-AI-GATEWAY-NONCE", nonce);
        headers.put("X-AI-GATEWAY-SIGNATURE", signature);

        return headers;
    }

    private static String urlEncode(String value) {
        try {
            return URLEncoder.encode(value, "UTF-8");
        } catch (Exception e) {
            // Log and handle the exception
            throw new RuntimeException("Error encoding URL", e);
        }
    }
}
